package com.verisette.ncos.web.card.action;

import java.awt.image.BufferedImage;
import java.io.File;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import javax.imageio.ImageIO;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.corp.agi.service.bean.ServiceRequest;
import org.corp.agi.service.bean.ServiceResponse;
import org.corp.agi.service.bean.UserBean;
import org.corp.agi.web.action.BaseAction;
import org.corp.agi.web.constant.WebConstant;
import org.corp.agi.web.util.ServiceRequestFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.verisette.ncos.common.ProjectConstant;
import com.verisette.ncos.persistence.dao.CardDAO;
import com.verisette.ncos.persistence.domain.MasterCompany;
import com.verisette.ncos.persistence.domain.MasterMember;
import com.verisette.ncos.persistence.domain.MasterTemplate;
import com.verisette.ncos.persistence.domain.MasterTemplateGroupToUsp;
import com.verisette.ncos.persistence.domain.MasterUserProfile;
import com.verisette.ncos.persistence.domain.TransCustomerOrder;
import com.verisette.ncos.service.card.gateway.CardService;
import com.verisette.ncos.web.card.bean.CardCreateBean;

@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class CreateCardAction extends BaseAction {
	
	private static final long serialVersionUID = 9010880837650025624L;
	
	private Logger logger = Logger.getLogger(CreateCardAction.class);
	private List<MasterTemplate> listAvaiTemplate;
	
	//input
	private CardCreateBean cardCreateBean;
	
	private String stepPage = "";
	private String stepBack = "N";
	
	private MasterTemplate selectedTemplate;
	private MasterMember member;
	private TransCustomerOrder order;
	
	private File mmbPicture;
    private String mmbPictureContentType;
    private String mmbPictureFileName;
    
    private Date cardCreateDate;
    
    private String x1;
    private String y1;
    private String w1;
    private String h1;
    
    private final int USER_SALE = 1;
    private final int USER_OFFICER = 2;
    
	//initial service
	private CardService cardService;
	@Autowired
	@Required
	public void setCardService(CardService cardService) {
		this.cardService = cardService;
	}
	
	private CardDAO cardDAO;
	@Autowired
	@Required
	public void setCardDAO(CardDAO cardDAO) {
		this.cardDAO = cardDAO;
	}
	
	private void resetForm(){
		stepPage = "pickTemplate";
		stepBack = "N";
		selectedTemplate=null;
		member=null;
		order=null;
		mmbPicture=null;
		mmbPictureContentType=null;
		mmbPictureFileName=null;
		cardCreateBean=new CardCreateBean();
		cardCreateBean.setPrintType("2");
		cardCreateBean.setCardCreateId(ProjectConstant.FILE_PDF_FORMAT.format(new Date()));
		cardCreateDate = new Date();
		
	}
	
	public String init() throws Exception{
		if(logger.isInfoEnabled()) {
			logger.info( this.getClass().getSimpleName() + ": init" );
		}
		System.out.println(String.format("~MtgID: %1$s", getMtgId()));

		httpServletRequest.getSession().setAttribute(ProjectConstant.SESSION_MENU_PAGE, ProjectConstant.MENU_PAGE_CREATE_CARD);
		
		stepPage = "pickTemplate";
		resetForm();
		ServiceResponse<List<MasterTemplate>> serviceResponse = cardService.inquiryCardTemplate(ServiceRequestFactory.getNewServiceRequest(httpServletRequest));
		if(isServiceResponseSuccess(serviceResponse)){
			listAvaiTemplate = serviceResponse.getValueObject();
		}
		
		if(logger.isDebugEnabled()){
			logger.debug("cardCreateDate:"+cardCreateDate);
		}
		
		return "pickTemplate";
	}
	
	public String pickTemplate() throws Exception {
		stepPage = "pickTemplate";
		restoreSessionToBean();
		return "pickTemplate";
	}
	
	public String fillData() throws Exception{
		if(logger.isInfoEnabled()) {
			logger.info( this.getClass().getSimpleName() + ": fillData" );
		}
		System.out.println(String.format("~MtgID: %1$s", getMtgId()));
		
		stepPage = "fillData";
		restoreSessionToBean();
		
		if(logger.isDebugEnabled()){
			logger.debug("cardCreateDate:"+cardCreateDate);
			if(cardCreateBean!=null){
				logger.debug(cardCreateBean.getOrder());
			}
		}
		MasterUserProfile userBean = (MasterUserProfile)httpServletRequest.getSession().getAttribute(WebConstant.SESSION_USERBEAN_KEY);
		int mtgId = userBean.getMasterTemplateGroupToUsp().getMasterTemplateGroup().getMtgId();
		cardCreateBean.getOrder().setMtgId(String.valueOf(mtgId));
		
		if(mtgId==2)
		{
			MasterCompany comp = userBean.getMasterCompany();
			if( null != comp )
			{
				cardCreateBean.getOrder().getMasterMember().setMmbOfficeNameTh(comp.getCompanyNameTh());
				cardCreateBean.getOrder().getMasterMember().setMmbOfficeNameEn(comp.getCompanyNameEn());
				cardCreateBean.getOrder().getMasterMember().setMmbOfficeAddrTh(comp.getCompanyAddrTh());
				cardCreateBean.getOrder().getMasterMember().setMmbOfficeAddrEn(comp.getCompanyAddrEn());
			}
		}
		
		storeBeanToSession();
		return "fillData";
	}
	
	public String preview() throws Exception{
		if(logger.isInfoEnabled()) {
			logger.info( this.getClass().getSimpleName() + ": preview" );
		}
		System.out.println(String.format("~MtgID: %1$s", getMtgId()));
		
		stepPage = "preview";
		restoreSessionToBean();
		
		if(logger.isDebugEnabled()){
			logger.debug("cardCreateDate:"+cardCreateDate);
			logger.debug(cardCreateBean);
		}
		
		cardCreateBean.getOrder().setCreatedDate(new Timestamp(System.currentTimeMillis()));

		MasterUserProfile userBean = (MasterUserProfile)httpServletRequest.getSession().getAttribute(WebConstant.SESSION_USERBEAN_KEY);
		String fileImgFormat = ProjectConstant.FILE_IMG_FORMAT.format(cardCreateDate);
		
		cardCreateBean.getOrder().setBranchAddrTh(userBean.getMasterBranch().getBranchAddrTh());
		
		//create pdf file
		String filePDFFormat = ProjectConstant.FILE_PDF_FORMAT.format(cardCreateDate);
		String pdfFileName = filePDFFormat.replaceAll(ProjectConstant.PARAM_USERNAME, userBean.getUsername());
		cardCreateBean.getOrder().setPdfPath(pdfFileName);
		
		createCardByTemplate();
		
		storeBeanToSession();
		return "preview";
	}
	
	public String send() throws Exception
	{
		if(LOG.isDebugEnabled()){
			logger.info("~ On Processing send ~");
		}
		System.out.println(String.format("~MtgID: %1$s", getMtgId()));
		
		stepPage = "send";
		restoreSessionToBean();
		
		cardCreateBean.getOrder().setQty(String.valueOf(cardCreateBean.getOrder().getQuantity()));
		cardCreateBean.getOrder().setPrintType(Integer.parseInt(cardCreateBean.getPrintType()));
		
		storeBeanToSession();
		
		if( 2 == getMtgId()){
			System.out.println("xxxxxxxxxxxxxxxx 1 "+cardCreateBean.getOrder().getDeliveryName());
			cardCreateBean.getOrder().setQuantity(Integer.parseInt(cardCreateBean.getOrder().getQty()));
			cardCreateBean.setDeliveryMobile("");
			cardCreateBean.setDeliveryMethod(0);
			cardCreateBean.getOrder().setPrintType(Integer.parseInt(cardCreateBean.getPrintType()));
			
			int id = cardCreateBean.getOrder().getMasterTemplate().getMtpId();
			MasterTemplate t = cardDAO.findMasterTemplateByID(id);
			
			cardCreateBean.getOrder().setMasterTemplate(t);
			System.out.println("xxxxxxxxxxxxxxxx 2");
			
			storeBeanToSession();
			
			return "send.officer";
		}
		return "send";
	}
	
	public String confirm() throws Exception
	{
		if(LOG.isDebugEnabled()){
			logger.info("~ On Processing confirm ~");
		}
		System.out.println(String.format("~MtgID: %1$s", getMtgId()));
		
		stepPage = "confirm";
		restoreSessionToBean();
		
		cardCreateBean.getOrder().setQuantity(Integer.parseInt(cardCreateBean.getOrder().getQty()));
		cardCreateBean.setDeliveryName(cardCreateBean.getOrder().getDeliveryName());
		cardCreateBean.setDeliveryAddr(cardCreateBean.getOrder().getDeliveryAddr());
		cardCreateBean.setDeliveryMobile(cardCreateBean.getOrder().getDeliveryMobile());
		cardCreateBean.setDeliveryMethod(cardCreateBean.getOrder().getDeliveryMethod());
		cardCreateBean.getOrder().setPrintType(Integer.parseInt(cardCreateBean.getPrintType()));
		
		int id = cardCreateBean.getOrder().getMasterTemplate().getMtpId();
		MasterTemplate t = cardDAO.findMasterTemplateByID(id);
		
		cardCreateBean.getOrder().setMasterTemplate(t);
		
		storeBeanToSession();
		
		return "confirm";
	}
	
	private void createCardByTemplate(){
		MasterUserProfile userBean = (MasterUserProfile)httpServletRequest.getSession().getAttribute(WebConstant.SESSION_USERBEAN_KEY);
		ServiceRequest<CardCreateBean> serviceRequest = ServiceRequestFactory.getNewServiceRequest(httpServletRequest);
		serviceRequest.setValueObject(cardCreateBean);
		ServiceResponse<CardCreateBean> serviceResponse = null;
		
		MasterTemplateGroupToUsp masterTemplateGroupToUsp = userBean.getMasterTemplateGroupToUsp();
		
		if(USER_SALE == masterTemplateGroupToUsp.getMasterTemplateGroup().getMtgId()){
			serviceResponse = cardService.createSaleCardByTemplate(serviceRequest);
		} else {
			serviceResponse = cardService.createOfficerCardByTemplate(serviceRequest);
		}
		if(isServiceResponseSuccess(serviceResponse)){
			cardCreateBean = serviceResponse.getValueObject();
		}
	}
	
	public String changeImage() throws Exception {
		restoreSessionToBean();
		if(logger.isDebugEnabled()){
			logger.debug(cardCreateBean);
		}
		storeBeanToSession();
		return "uploadAndCropImage";
	}
	
	public String uploadImage() throws Exception {
		restoreSessionToBean();
		UserBean userBean = (UserBean)httpServletRequest.getSession().getAttribute(WebConstant.SESSION_USERBEAN_KEY);
		String fileImgFormat = ProjectConstant.FILE_IMG_FORMAT.format(cardCreateDate);
		//Save pictureName
		if(mmbPicture!=null && mmbPicture.exists()){
			String mmbPictureFileExtention = mmbPictureFileName.substring(mmbPictureFileName.lastIndexOf('.'));
			if(logger.isDebugEnabled()) logger.debug("#####     mmbPictureFileExtention=" + mmbPictureFileExtention);
			if(logger.isDebugEnabled()) logger.debug("#####     mmbPictureFileName=" + mmbPictureFileName);
			String imageFileName = fileImgFormat.replaceAll(ProjectConstant.PARAM_USERNAME, userBean.getUsername()) + mmbPictureFileExtention;
			if(logger.isDebugEnabled()) logger.debug("#####     imageFileName=" + imageFileName);
			if(cardCreateBean!=null && cardCreateBean.getOrder().getMasterMember()!=null){
				if(cardCreateBean.getOrder().getMasterMember().getMmbPicturePath()!=null && 
					!"".equals(cardCreateBean.getOrder().getMasterMember().getMmbPicturePath())){
					imageFileName = cardCreateBean.getOrder().getMasterMember().getMmbPicturePath();
					String oldMmbPictureFileExtention = imageFileName.substring(imageFileName.lastIndexOf('.'));
					if(!mmbPictureFileExtention.equalsIgnoreCase(oldMmbPictureFileExtention)){
						imageFileName = imageFileName.replace(oldMmbPictureFileExtention, mmbPictureFileExtention);
					}
				}
			}

			if(logger.isDebugEnabled()) logger.debug("#####     imageFileName(final)=" + imageFileName);
			
			//${UserBean.username}_Y${yyyy}M${MM}D${dd}H${HH}m${mm}s${ss}_${SSS}
			File destFile = new File(ProjectConstant.APP_TEMP_IMG_FOLDER + "\\" + imageFileName);
			FileUtils.copyFile(mmbPicture, destFile);
			
			httpServletRequest.getSession().setAttribute("session_mmbPicture", mmbPicture);
			
			cardCreateBean.getOrder().getMasterMember().setMmbPicturePath(destFile.getName());
			if(logger.isDebugEnabled()) logger.debug(cardCreateBean.getOrder().getMasterMember().getMmbPicturePath());
		}

		storeBeanToSession();

		return "uploadAndCropImage";
	}
	
	public String cropImage(){
		
		restoreSessionToBean();
		stepPage="fillData";
		try{
			if(logger.isDebugEnabled()) logger.debug(String.format("x1=%s,y1=%s,w1=%s,h1=%s", this.x1, this.y1, this.w1, this.h1));
			double x1 = Double.parseDouble(this.x1);
			double y1 = Double.parseDouble(this.y1);
			double w1 = Double.parseDouble(this.w1);
			double h1 = Double.parseDouble(this.h1);
			
			String imageFileName = cardCreateBean.getOrder().getMasterMember().getMmbPicturePath();
			if(logger.isDebugEnabled()) logger.debug("###   imageFileName=" + imageFileName);
			mmbPicture = new File(ProjectConstant.APP_TEMP_IMG_FOLDER + "\\" + imageFileName);
			if(logger.isDebugEnabled()) logger.debug("###   mmbPicture.getName()=" + mmbPicture.getName());
			BufferedImage image=ImageIO.read(mmbPicture);
			
			//adjust scale to actual
			int imgWidth = image.getWidth();
			int imgHeight = image.getHeight();
			int targetHeight = 180;
			double hratio = 1D;
			if(imgHeight>targetHeight){
				hratio = (double)imgHeight / targetHeight;
				
				x1 *= hratio;
				y1 *= hratio;
				w1 *= hratio;
				h1 *= hratio;
			}

			int x = (int)Math.round(x1);
			int y = (int)Math.round(y1);
			int w = (int)Math.round(w1);
			int h = (int)Math.round(h1);

			if(logger.isDebugEnabled()) logger.debug(String.format("x=%s,y=%s,w=%s,h=%s", x, y, w, h));
			
			BufferedImage out=image.getSubimage(x,y,w,h);
			File destFile = new File(ProjectConstant.APP_TEMP_IMG_FOLDER + "\\" + imageFileName);
			if(logger.isDebugEnabled()) logger.debug("###   destFile.getName()=" + destFile.getName());
			String extension = imageFileName.substring(imageFileName.lastIndexOf('.')+1);
			if(logger.isDebugEnabled()) logger.debug("###   extension=" + extension);
			ImageIO.write(out,extension,destFile);
			return "fillData";
		}catch(Exception ex){
			ex.printStackTrace();
		}finally{
		}
		
		return "fillData";
	}
	
	public String save() throws Exception{
		if(logger.isInfoEnabled()) {
			logger.info( this.getClass().getSimpleName() + ": save" );
		}
		System.out.println(String.format("~MtgID: %1$s", getMtgId()));
		
		stepPage = "save";
		if(logger.isDebugEnabled()){
			logger.debug(cardCreateBean);
		}
		
		int iDeliveryAddUse = 2;
		if( !StringUtils.isEmpty(cardCreateBean.getOrder().getTxtDeliveryAddrUse()) )
		{
			iDeliveryAddUse = Integer.parseInt(cardCreateBean.getOrder().getTxtDeliveryAddrUse());
		}
		
		if( !StringUtils.isEmpty(cardCreateBean.getPrintType()) )
		{
			cardCreateBean.getOrder().setPrintType(Integer.parseInt(cardCreateBean.getPrintType()));
		}
		
		cardCreateBean.getOrder().setDeliveryAddrUse(iDeliveryAddUse);
		cardCreateBean.getOrder().setQuantity(Integer.parseInt(cardCreateBean.getOrder().getQty()));
		cardCreateBean.getOrder().setDeliveryName(cardCreateBean.getDeliveryName());
		cardCreateBean.getOrder().setDeliveryAddr(cardCreateBean.getDeliveryAddr());
		cardCreateBean.getOrder().setDeliveryMobile(cardCreateBean.getDeliveryMobile());
		cardCreateBean.getOrder().setDeliveryMethod(cardCreateBean.getDeliveryMethod());
		
		ServiceRequest<CardCreateBean> serviceRequest = ServiceRequestFactory.getNewServiceRequest(httpServletRequest);
		serviceRequest.setValueObject(cardCreateBean);
		cardCreateBean = cardService.saveCardByTemplate(serviceRequest).getValueObject();
		storeBeanToSession();
		if(2 == getMtgId()) {
			return "save.officer";
		}
		return "save";
	}
	
	private static final String SESSION_CARDCREATEBEAN = "SESSION_CARDCREATEBEAN";
	
	private void restoreSessionToBean(){
		if(logger.isDebugEnabled()) logger.debug("stepBack=" + stepBack);
		if("Y".equals(stepBack)){
			if(httpServletRequest.getSession().getAttribute(SESSION_CARDCREATEBEAN)!=null){
				cardCreateBean = (CardCreateBean)httpServletRequest.getSession().getAttribute(SESSION_CARDCREATEBEAN);
			}
		}
	}
	
	private int getMtgId(){
		MasterUserProfile userBean = (MasterUserProfile)httpServletRequest.getSession()
				.getAttribute(WebConstant.SESSION_USERBEAN_KEY);
		return userBean.getMasterTemplateGroupToUsp()
				.getMasterTemplateGroup().getMtgId();
	}
	
	private void storeBeanToSession(){
		httpServletRequest.getSession().setAttribute(SESSION_CARDCREATEBEAN, cardCreateBean);
	}
	
	public List<MasterTemplate> getListAvaiTemplate() {
		return listAvaiTemplate;
	}
	
	public void setListAvaiTemplate(List<MasterTemplate> listAvaiTemplate) {
		this.listAvaiTemplate = listAvaiTemplate;
	}

	public MasterTemplate getSelectedTemplate() {
		return selectedTemplate;
	}
	
	public void setSelectedTemplate(MasterTemplate selectedTemplate) {
		this.selectedTemplate = selectedTemplate;
	}
	
	public MasterMember getMember() {
		return member;
	}
	
	public void setMember(MasterMember member) {
		this.member = member;
	}
	
	public TransCustomerOrder getOrder() {
		return order;
	}
	
	public void setOrder(TransCustomerOrder order) {
		this.order = order;
	}
	
	public File getMmbPicture() {
		return mmbPicture;
	}
	
	public void setMmbPicture(File mmbPicture) {
		this.mmbPicture = mmbPicture;
	}
	
	public String getMmbPictureContentType() {
		return mmbPictureContentType;
	}
	
	public void setMmbPictureContentType(String mmbPictureContentType) {
		this.mmbPictureContentType = mmbPictureContentType;
	}
	
	public String getMmbPictureFileName() {
		return mmbPictureFileName;
	}
	
	public void setMmbPictureFileName(String mmbPictureFileName) {
		this.mmbPictureFileName = mmbPictureFileName;
	}
	
	public CardCreateBean getCardCreateBean() {
		return cardCreateBean;
	}
	
	public void setCardCreateBean(CardCreateBean cardCreateBean) {
		this.cardCreateBean = cardCreateBean;
	}

	public Date getCardCreateDate() {
		return cardCreateDate;
	}

	public void setCardCreateDate(Date cardCreateDate) {
		this.cardCreateDate = cardCreateDate;
	}

	public String getStepPage() {
		return stepPage;
	}

	public void setStepPage(String stepPage) {
		this.stepPage = stepPage;
	}

	public String getStepBack() {
		return stepBack;
	}

	public void setStepBack(String stepBack) {
		this.stepBack = stepBack;
	}

	public String getX1() {
		return x1;
	}

	public void setX1(String x1) {
		this.x1 = x1;
	}

	public String getY1() {
		return y1;
	}

	public void setY1(String y1) {
		this.y1 = y1;
	}

	public String getW1() {
		return w1;
	}

	public void setW1(String w1) {
		this.w1 = w1;
	}

	public String getH1() {
		return h1;
	}

	public void setH1(String h1) {
		this.h1 = h1;
	}
}
